package dragon

import (
  "fmt"
	"http"
	"template"
	"time"
	"strconv"
	"os"
	"math"
  "io"

	"appengine"
	"appengine/datastore"
  "appengine/urlfetch"
)

const recaptcha = `http://www.google.com/recaptcha/api/verify?privatekey=%s&remoteip=%s&challenge=%s&response=%s`

type entry struct {
	Nick    string
	Email	string
	Www	string
	Content []byte
	Date    datastore.Time
}

type entry4tmpl struct {
	Nick    string
	Email	string
	Www	string
	Content []byte
	Date    string
	Key	string
}

func handleGuestbook(w http.ResponseWriter, r *http.Request) {
	const pagelenPath = len(guestbookpageURL)
	const limit = 5
	var page = 1
	var e []*entry
	var cs []*counters
	var err os.Error

	if !isAllDigits(r.URL.Path[pagelenPath:]) {
		http.Redirect(w, r, guestbookpageURL+"1", http.StatusFound)
		return
	}
	page, err = strconv.Atoi(r.URL.Path[pagelenPath:])
	if err != nil {
		http.Redirect(w, r, guestbookpageURL+"1", http.StatusFound)
		return
	}

	c := appengine.NewContext(r)
	q := datastore.NewQuery("entry").
		Order("-Date").
		Offset((page-1)*limit).
		Limit(limit)
	ks, err := q.GetAll(c, &e)
	if err != nil {
		http.Redirect(w, r, "/static/err.html", http.StatusFound)
                return
	}
	q = datastore.NewQuery("counters").Filter("Kind =", "ksiega").Limit(1)
	csks, _ := q.GetAll(c, &cs)
	if len(csks) == 0 {
		addCounter("ksiega", c)
		q.GetAll(c, &cs)
	}

	e4t := make([]entry4tmpl, len(e))

        for k := range ks {
		e4t[k].Nick = e[k].Nick
		e4t[k].Email = e[k].Email
		e4t[k].Www = e[k].Www
		e4t[k].Content = e[k].Content
		date := e[k].Date.Time()
		e4t[k].Date = prettyDate(date)
        }

	funcs := template.FuncMap{
                "markdown": markdownBasic,
		"selector": selector,
        }
	mapa := map[string]interface{} {
		"Entries": e4t,
		"Site": count(c, r, w),
		"Count": cs[0].Count,
		"Mapa": map[string]interface{} {
			"Pages": int(math.Ceil(float64(cs[0].Count)/limit)),
			"Page": page,
		},
	}
    
	ts := new(template.Set)
        troot, _ := template.New("root").
		Funcs(template.FuncMap{
			"date": stuffDate,
		}).
		ParseFile("templates/root.html")
	tguestbook, _ := template.New("content").Funcs(funcs).
		ParseFile("templates/guestbook.html")
	ts.Add(troot, tguestbook)
	ts.Execute(w, "root", mapa)
}

func handleAdminGuestbook(w http.ResponseWriter, r *http.Request) {
	var e []*entry

	c := appengine.NewContext(r)
	q := datastore.NewQuery("entry").Order("-Date")
	ks, _ := q.GetAll(c, &e)

	e4t := make([]entry4tmpl, len(e))

        for k := range ks {
		e4t[k].Nick = e[k].Nick
		e4t[k].Email = e[k].Email
		e4t[k].Www = e[k].Www
		e4t[k].Content = e[k].Content
		date := e[k].Date.Time()
		e4t[k].Date = prettyDate(date)
		e4t[k].Key = ks[k].Encode()
        }

	ts := new(template.Set)
	tadmin, _ := template.New("admin").
		ParseFile("templates/admin.html")
	tguestbook, _ := template.New("content").
		ParseFile("templates/admin-guestbook.html")
	ts.Add(tadmin, tguestbook)
	ts.Execute(w, "admin", e4t)
}

func handleGuestbookAdd(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)

	if r.Method != "POST" {
		ts := new(template.Set)
                troot, _ := template.New("root").
			Funcs(template.FuncMap{
				"date": stuffDate,
			}).
                        ParseFile("templates/root.html")
                tguestbookadd, _ := template.New("content").
                        ParseFile("templates/guestbook-add.html")
                ts.Add(troot, tguestbookadd)
                ts.Execute(w, "root", map[string]interface{}{"Site": count(c, r, w),})
                return
	}

	r.ParseForm()
	e := &entry{
		Nick:    r.FormValue("nick"),
		Email:	 r.FormValue("email"),
		Www:	 r.FormValue("www"),
		Content: []byte(r.FormValue("content")),
		Date:    datastore.SecondsToTime(time.Seconds()),
	}

  client := urlfetch.Client(c)
  tmpURL := fmt.Sprintf(recaptcha, "6LfRfdASAAAAAFZxDYu4qLKoyQRN2FwzcHE4Fyei",
                        "192.168.1.1",
                        r.FormValue("recaptcha_challenge_field"),
                        r.FormValue("recaptcha_response_field"))
  resp, _ := client.Get(tmpURL)
  
  b := make([]byte, 1)

  io.ReadFull(resp.Body, b)

  if b[0] == 't' {
	  _, err := datastore.Put(c, datastore.NewIncompleteKey(c, "entry", nil), e)
	  if err != nil {
	  	http.Redirect(w, r, "/static/err.html", http.StatusFound)
	  	return
	  }
	  updateCount("ksiega", c, true);
	  http.Redirect(w, r, guestbookpageURL+"1", http.StatusFound)
  } else {
    var e4t entry4tmpl

    e4t.Nick = r.FormValue("nick")
    e4t.Email = r.FormValue("email")
    e4t.Www = r.FormValue("www")
    e4t.Content = []byte(r.FormValue("content"))

		ts := new(template.Set)
    troot, _ := template.New("root").
			Funcs(template.FuncMap{
				"date": stuffDate,
			}).
                        ParseFile("templates/root.html")
                tguestbookadd, _ := template.New("content").
                        ParseFile("templates/guestbook-add.html")
                ts.Add(troot, tguestbookadd)
                ts.Execute(w, "root", map[string]interface{}{"Site": count(c, r, w), "Entries": e4t,})
                return
  }
}

func handleGuestbookEdit(w http.ResponseWriter, r *http.Request) {
        const lenPath = len(admguestbookeditURL)
        k, err := datastore.DecodeKey(r.URL.Path[lenPath:])
        if err != nil {
                http.Redirect(w, r, "/", http.StatusFound)
                return
        }

        if r.Method != "POST" {
                var e entry
                var e4t entry4tmpl

                c := appengine.NewContext(r)
                datastore.Get(c, k, &e)

                e4t.Nick = e.Nick
                e4t.Email = e.Email
                e4t.Www = e.Www
                e4t.Content = e.Content
                e4t.Key = k.Encode()

                ts := new(template.Set)
                tadmin, _ := template.New("admin").ParseFile("templates/admin.html")
                tguestbookedit, _ := template.New("content").
                        ParseFile("templates/guestbook-edit.html")
                ts.Add(tadmin, tguestbookedit)
                ts.Execute(w, "admin", e4t)
                return
        }

        c := appengine.NewContext(r)
        r.ParseForm()
        e := &entry{
                Nick:    r.FormValue("nick"),
                Email:   r.FormValue("email"),
                Www:     r.FormValue("www"),
                Content: []byte(r.FormValue("content")),
        }
        datastore.Delete(c, k)
        datastore.Put(c, k, e)
        http.Redirect(w, r, admguestbookURL, http.StatusFound)
}

func handleGuestbookDelete(w http.ResponseWriter, r *http.Request) {
        const lenPath = len(admguestbookdelURL)

        c := appengine.NewContext(r)
        k, err := datastore.DecodeKey(r.URL.Path[lenPath:])
        if err != nil {
                http.Redirect(w, r, "/", http.StatusFound)
                return
        }
        err = datastore.Delete(c, k)
	if err != nil {
                http.Redirect(w, r, "/static/err.html", http.StatusFound)
                return
        }
        updateCount("ksiega", c, false);
        http.Redirect(w, r, admguestbookURL, http.StatusFound)
}
